﻿using CLM.Gestao.Administrador.DAL;
using CLM.Gestao.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;

namespace CLM.Gestao.Custos.BLL
{
    public class Lancamento : LancamentoBLO<TB_LANCAMENTO>
    {
        #region Propriedades

        public int IdLancamento { get; set; }
        public int IdCentroCusto { get; set; }
        public int IdContaContabil { get; set; }
        public int IdLancamentoTipo { get; set; }
        public int IdProjeto { get; set; }
        public DateTime DataLancamento { get; set; }
        public decimal ValorLancamento { get; set; }
        public DateTime DataEntradaSun { get; set; }
        public int IdPeriodo { get; set; }
        public DateTime DataInclusao { get; set; }
        public string DescricaoLancamento { get; set; }
        public int IdEvento { get; set; }
        public int IdFuncionario { get; set; }
        public int IdMapaEstrategicoItem { get; set; }
        public bool IndicaDespesaComprometida { get; set; }
        public string ContratoDespesaComprometida { get; set; }
        public int idLancamentoCusto { get; set; }
        public int IdProduto { get; set; }
        public string CodigoProdutoGlobal { get; set; }
        public string NomeProdutoGlobal { get; set; }
        public int? IdIndicadorCusto { get; set; }
        
        #endregion Propriedades

        #region Conversões

        private List<TB_LANCAMENTO> ConvertToEDM(List<Lista> pLista)
        {
            List<TB_LANCAMENTO> List = (from l in pLista
                                        select new TB_LANCAMENTO
                                        {
                                            CONTRATO_DESPESA_COMPROMETIDA = l.ContratoDespesaComprometida,
                                            DATA_INCLUSAO = DateTime.Parse(l.DataInclusao.ToString()),
                                            DATA_LANCAMENTO = DateTime.Parse(l.DataLancamento.ToString()),
                                            DESCRICAO_LANCAMENTO = l.DescricaoLancamento,
                                            ID_CENTRO_CUSTO = int.Parse(l.IdCentroCusto.ToString()),
                                            ID_CONTA_CONTABIL = int.Parse(l.IdContaContabil.ToString()),
                                            ID_EVENTO = int.Parse(l.IdEvento.ToString()),
                                            ID_FUNCIONARIO = int.Parse(l.IdFuncionario.ToString()),
                                            ID_LANCAMENTO_TIPO = int.Parse(l.IdLancamentoTipo.ToString()),
                                            ID_LANCAMENTO = int.Parse(l.IdLancamento.ToString()),
                                            ID_MAPA_ESTRATEGICO_ITEM = int.Parse(l.IdMapaEstrategicoItem.ToString()),
                                            ID_PERIODO = int.Parse(l.IdPeriodo.ToString()),
                                            ID_PROJETO = int.Parse(l.IdProjeto.ToString()),
                                            INDICA_DESPESA_COMPROMETIDA = bool.Parse(l.IndicaDespesaComprometida.ToString()),
                                            VALOR_LANCAMENTO = decimal.Parse(l.ValorLancamento.ToString())
                                        }).ToList();
            return List;
        }

        private List<Lista> ConvertToContext(IQueryable<TB_LANCAMENTO> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    ContratoDespesaComprometida = l.CONTRATO_DESPESA_COMPROMETIDA,
                                    DataInclusao = l.DATA_INCLUSAO,
                                    DataLancamento = l.DATA_LANCAMENTO,
                                    DescricaoLancamento = l.DESCRICAO_LANCAMENTO,
                                    IdCentroCusto = l.ID_CENTRO_CUSTO,
                                    IdContaContabil = l.ID_CONTA_CONTABIL,
                                    IdEvento = l.ID_EVENTO,
                                    IdFuncionario = l.ID_FUNCIONARIO,
                                    IdLancamentoTipo = l.ID_LANCAMENTO_TIPO,
                                    IdLancamento = l.ID_LANCAMENTO,
                                    IdLancamentoCusto = l.TB_LANCAMENTO_CUSTO.Select(s => s.ID_LANCAMENTO_CUSTO).FirstOrDefault(),
                                    IdMapaEstrategicoItem = l.ID_MAPA_ESTRATEGICO_ITEM,
                                    IdIndicadorCusto = l.TB_LANCAMENTO_CUSTO.Select(s => s.ID_INDICADOR_CUSTO).FirstOrDefault(),
                                    IdPeriodo = l.ID_PERIODO,
                                    IdProduto = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.ID_PRODUTO).FirstOrDefault(),
                                    IdProjeto = l.ID_PROJETO,
                                    IndicaDespesaComprometida = l.INDICA_DESPESA_COMPROMETIDA,
                                    ValorLancamento = l.VALOR_LANCAMENTO,
                                    CodigoProdutoGlobal = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_GLOBAL.CODIGO_PRODUTO_GLOBAL).FirstOrDefault(),
                                    NomeProdutoFamilia = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_FAMILIA.NOME_PRODUTO_FAMILIA).FirstOrDefault(),
                                    NomeProdutoGlobal = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_GLOBAL.NOME_PRODUTO_GLOBAL).FirstOrDefault()
                                }).ToList();
            return List;
        }

        private List<Lista> ConvertToContextPNL(IQueryable<TB_LANCAMENTO> pContext)
        {
            List<Lista> List = (from l in pContext
                                select new Lista
                                {
                                    //ContratoDespesaComprometida = l.CONTRATO_DESPESA_COMPROMETIDA,
                                    //DataInclusao = l.DATA_INCLUSAO,
                                    //DataLancamento = l.DATA_LANCAMENTO,
                                    //DescricaoLancamento = l.DESCRICAO_LANCAMENTO,
                                    //IdCentroCusto = l.ID_CENTRO_CUSTO,
                                    //IdContaContabil = l.ID_CONTA_CONTABIL,
                                    //IdEvento = l.ID_EVENTO,
                                    //IdFuncionario = l.ID_FUNCIONARIO,
                                    //IdLancamentoTipo = l.ID_LANCAMENTO_TIPO,
                                    //IdLancamento = l.ID_LANCAMENTO,
                                    //IdLancamentoCusto = l.TB_LANCAMENTO_CUSTO.Select(s => s.ID_LANCAMENTO_CUSTO).FirstOrDefault(),
                                    //IdMapaEstrategicoItem = l.ID_MAPA_ESTRATEGICO_ITEM,
                                    IdIndicadorCusto = l.TB_LANCAMENTO_CUSTO.Select(s => s.ID_INDICADOR_CUSTO).FirstOrDefault(),
                                    IdPeriodo = l.ID_PERIODO,
                                    //IdProduto = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.ID_PRODUTO).FirstOrDefault(),
                                    //IdProjeto = l.ID_PROJETO,
                                    //IndicaDespesaComprometida = l.INDICA_DESPESA_COMPROMETIDA,
                                    ValorLancamento = l.VALOR_LANCAMENTO,
                                    //CodigoProdutoGlobal = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_GLOBAL.CODIGO_PRODUTO_GLOBAL).FirstOrDefault(),
                                    NomeProdutoFamilia = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_FAMILIA.NOME_PRODUTO_FAMILIA).FirstOrDefault()
                                    //NomeProdutoGlobal = l.TB_LANCAMENTO_CUSTO.Select(s => s.TB_PRODUTO.TB_PRODUTO_GLOBAL.NOME_PRODUTO_GLOBAL).FirstOrDefault()
                                }).ToList();
            return List;
        }
        #endregion Conversões

        #region CRUD
        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Add(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Add(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Delete(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Delete(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="pLista"></param>
        public void Update(List<Lista> pLista)
        {
            try
            {
                foreach (var item in ConvertToEDM(pLista))
                    base.Update(item);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        /// <summary>
        /// Efetua a pesquisa na tabela, filtrando as solicitações do usuário
        /// </summary>
        /// <param name="pPesquisa">pPesquisa</param>
        /// <returns>Lista</returns>
        private IQueryable<TB_LANCAMENTO> Get(Lista pPesquisa)
        {
            IQueryable<TB_LANCAMENTO> Consulta;

            Consulta = from p in GetAll()
                       select p;

            if (pPesquisa != null)
            {
                if (pPesquisa.IdPeriodo > 0)
                    Consulta = from p in Consulta where p.ID_PERIODO == pPesquisa.IdPeriodo select p;

                if (pPesquisa.IdLancamentoTipo > 0)
                    Consulta = from p in Consulta where p.ID_LANCAMENTO_TIPO == pPesquisa.IdLancamentoTipo select p;
            }
            return Consulta;
        }

        #endregion CRUD

        #region Retorna Listas e Itens

        public List<Lista> GetLista()
        {
            return GetLista(new Lista());
        }

        public List<Lista> GetLista(Lista pPesquisa)
        {
            var ListaLancamento = ConvertToContext(Get(pPesquisa));
            return ListaLancamento;
        }

        public List<Lista> GetListaPNL(Lista pPesquisa)
        {
            var ListaLancamento = ConvertToContextPNL(Get(pPesquisa));
            return ListaLancamento;
        }

        #endregion Retorna Listas e Itens

        #region Consultas


        #endregion Consultas

        #region Classes

        /// <summary>
        /// Lista com as propriedades da classe
        /// </summary>
        public class Lista
        {
            public int IdLancamento { get; set; }
            public int? IdCentroCusto { get; set; }
            public int? IdContaContabil { get; set; }
            public int? IdLancamentoTipo { get; set; }
            public int? IdProjeto { get; set; }
            public int? IdIndicadorCusto { get; set; }
            public int IdLancamentoCusto { get; set; }
            public DateTime? DataLancamento { get; set; }
            public decimal? ValorLancamento { get; set; }
            public int? IdPeriodo { get; set; }
            public DateTime? DataInclusao { get; set; }
            public string DescricaoLancamento { get; set; }
            public int? IdEvento { get; set; }
            public int? IdFuncionario { get; set; }
            public int? IdMapaEstrategicoItem { get; set; }
            public bool? IndicaDespesaComprometida { get; set; }
            public string ContratoDespesaComprometida { get; set; }
            public int IdProduto { get; set; }
            public string CodigoProdutoGlobal { get; set; }
            public string NomeProdutoGlobal { get; set; }
            public string NomeProdutoFamilia { get; set; }
        }

        #endregion Classes
    }

    public class LancamentoBLO<T> where T : TB_LANCAMENTO
    {
        /// <summary>
        /// LancamentoDAO
        /// </summary>
        private LancamentoDAO<T> _base = new LancamentoDAO<T>();

        /// <summary>
        /// Adiciona uma entidade no sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Add(T pEntity)
        {
            Validate(pEntity);
            _base.Add(pEntity);
            //return _base.Save(pEntity);
        }

        /// <summary>
        /// Salva uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Save()
        {
            _base.Save();
        }

        /// <summary>
        /// Deleta uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        public void Delete(T pEntity)
        {
            _base.Delete(pEntity);
            //_base.Save(pEntity);
        }

        /// <summary>
        /// Atualiza uma entidade do sistema
        /// </summary>
        /// <param name="pEntity">pEntity</param>
        /// <returns>Entidade</returns>
        public void Update(T pEntity)
        {
            Validate(pEntity);
            _base.Update(pEntity);
            //return _base.Save(pEntity);
        }

        /// <summary>
        /// Recupera uma entidade do sistema
        /// </summary>
        /// <returns>Lista</returns>
        public IQueryable<TB_LANCAMENTO> GetAll()
        {
            return _base.GetAllCustos();
        }

        /// <summary>
        /// Valida a consistência da Entidade antes de 'comitar' a transação
        /// </summary>
        /// <param name="pEntity">Entidade</param>
        public void Validate(T pEntity)
        {

        }
    }
}